Skip to content

uefi-raw: Add binding for EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL #1658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

seijikun
Copy link
Contributor

@seijikun seijikun commented May 7, 2025

Checklist

  • Sensible git history (for example, squash "typo" or "fix" commits). See the Rewriting History guide for help.
  • Update the changelog (if necessary)

@seijikun
Copy link
Contributor Author

seijikun commented May 7, 2025

No idea what the CI is complaining about, tbh.
Is it because the variants are called Uint8, Uint16, etc.?

I'm still quite unsure about how we should handle this: *mut Self here, because a normal read may (depending on the device) change the PCI device's internal state just as much as a write.
Should we just make both take a mutable pointer?

@seijikun seijikun force-pushed the mr-pciroot branch 2 times, most recently from 7357644 to 4adcc5c Compare May 7, 2025 16:29
@seijikun seijikun marked this pull request as draft May 7, 2025 16:32
@nicholasbishop
Copy link
Member

No idea what the CI is complaining about, tbh.

Currently just a couple minor clippy things, add must_use and const: https://github.com/rust-osdev/uefi-rs/actions/runs/14888659415/job/41814946880?pr=1658

Should we just make both take a mutable pointer?

Yep, when in doubt let's go with *mut in uefi-raw.

@seijikun seijikun force-pushed the mr-pciroot branch 2 times, most recently from 397aafc to 4dd2a16 Compare May 8, 2025 08:20
@seijikun
Copy link
Contributor Author

seijikun commented May 8, 2025

Aight, when in doubt, *mut it out.
I made every method of which I think might change the device's state/memory in any way as *mut.

This is the error I don't really understand:
image

@seijikun seijikun marked this pull request as ready for review May 8, 2025 11:57
@phip1611
Copy link
Member

phip1611 commented May 8, 2025

The error reporting of the check-raw step is rather poor, I agree. You can run cargo xtask check-raw locally (sources are in <repo>/xtask/src) and debug into to look up what's wrong; feel free to add an improvement to the error reporting as well

@nicholasbishop
Copy link
Member

nicholasbishop commented May 8, 2025

Ah sorry I missed that error. It's because you're using a Rust enum, which is not quite compatible with a C enum (because it's undefined behavior to create a Rust enum from an invalid value).

This can be fixed by using the newtype_enum macro.

(I put up #1660 to improve this error message.)

@seijikun seijikun force-pushed the mr-pciroot branch 3 times, most recently from 6fd55f5 to 45b4059 Compare May 8, 2025 19:24
@seijikun
Copy link
Contributor Author

seijikun commented May 8, 2025

This can be fixed by using the newtype_enum macro.

Oof, that's embarrassing, the last merge request was only a few weeks ago and I've already forgotten about it.

I needed some iterations for the addressing stuff (PciIoAddress), but now I'm quite happy with it.


#[derive(Debug)]
#[repr(C)]
pub struct PciRootBridgeIoAccess<TAddr> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The uefi-raw crate doesn't normally use generics. I think in the spec the address is treated as u64 in all cases, even though for for pci specifically the u64 is broken down into subfields, so let's do that and leave higher-level abstractions to the uefi crate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the interface itself in the spec accepts a u64, because they use the same struct for pci, memory and io.
But the pci one is supposed to be filled by something like this:

#define EFI_PCI_ADDRESS(bus, dev, func, reg) \
  (UINT64) ( \
  (((UINTN) bus) << 24) | \
  (((UINTN) dev) << 16) | \
  (((UINTN) func) << 8) | \
  (((UINTN) (reg)) < 256 ? ((UINTN) (reg)) : (UINT64) (LShiftU64 ((UINT64) (reg), 32))))

My thought process was: If they could have used templates/generics in their interface, they would have done it there.

At least I would like to have the PCI addressing somehow as part of the unsafe API, because otherwise you can't use it without reading the UEFI spec. Do you have an alternative suggestion? The only alternative I was able to come up with, was a union and that's IMHO ugly to use.

Copy link
Contributor Author

@seijikun seijikun May 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to get rid of the generics, we could:

impl Into<u64> for PciIoAddress {
    fn into(self) -> u64 {
        unsafe { core::mem::transmute(self) }
    }
}

And then use it like so:

let addr = PciIoAddress::new(1, 3, 3).with_register(7);
(raw_proto.pci.read)(
    raw_proto,
    PciRootBridgeIoProtocolWidth::UINT32,
    addr.into(), // API takes u64, we convert PciIoAddress to it
    1,
    &mut raw as *mut u32 as *mut c_void
).to_result()?;

EDIT: Just refactored it that way

@seijikun seijikun force-pushed the mr-pciroot branch 3 times, most recently from 6901e11 to 7814063 Compare May 12, 2025 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants